﻿using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Globalization;
using System.Security.Cryptography;

using Microsoft.SqlServer.Server;
using System.Collections;
using System.Collections.Generic;

namespace PickGold.SqlServer
{
	/// <summary>
	/// Common
	/// </summary>
	public static class Other
	{
		/// <summary>1970-1-1 62135596800000 ms</summary>
		public const long JS_1970 = 62135596800000L;
		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlGuid GetGuid(SqlString input, SqlGuid value)
		{
			if (input.IsNull)
				return SqlGuid.Null;

			var t = input.Value;
			if (string.IsNullOrEmpty(t))
				return SqlGuid.Null;

			try
			{
				value = SqlGuid.Parse(t);
			}
			catch (Exception x)
			{
				if (value.IsNull)
					throw new Exception("[" + t + "] " + x.Message, x);
			}

			return value;
		}

		#region Combine time to guid or guid to time

		/// <summary>
		/// 以指定的日期初始化 System.Data.SqlTypes.SqlGuid 类的一个新实例。
		/// </summary>
		/// <param name="guid"></param>
		/// <param name="date">指定的日期</param>
		/// <param name="endian"></param>
		/// <returns>新的 System.Data.SqlTypes.SqlGuid 对象。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlGuid GetIdByDays(SqlGuid guid, SqlDateTime date, SqlBoolean endian)
		{
			if (date.IsNull)
				return SqlGuid.Null;

			var s = (ushort)new TimeSpan(new DateTime(date.Value.Year % 179 + 1, date.Value.Month, date.Value.Day).Ticks).TotalDays;
			var bs = guid.IsNull ? Guid.Empty.ToByteArray() : guid.ToByteArray();
			var bsDt = BitConverter.GetBytes(s);
			if ((endian.IsNull && BitConverter.IsLittleEndian) || (!endian.IsNull && endian.Value == true))
			{
				bs[10] = bsDt[1];
				bs[11] = bsDt[0];
			}
			else
			{
				bs[10] = bsDt[0];
				bs[11] = bsDt[1];
			}
			return new SqlGuid(bs);
		}

		/// <summary>
		/// 从指定的 System.Guid 类的一个实例中取出时间值
		/// </summary>
		/// <param name="guid">指定的 System.Guid 类的一个实例</param>
		/// <param name="endian"></param>
		/// <returns>指定的 System.Guid 类的一个实例中的时间值</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt32 GetDaysFromId(SqlGuid guid, SqlBoolean endian)
		{
			if (guid.IsNull)
				return SqlInt32.Null;

			var bs = guid.ToByteArray();
			if ((endian.IsNull && BitConverter.IsLittleEndian) || (!endian.IsNull && endian.Value == true))
				bs = new byte[] { bs[11], bs[10] };
			else
				bs = new byte[] { bs[10], bs[11] };
			return new SqlInt32(BitConverter.ToUInt16(bs, 0));
		}

		/// <summary>
		/// 以指定的刻度初始化 System.Data.SqlTypes.SqlGuid 类的一个新实例。
		/// </summary>
		/// <param name="guid"></param>
		/// <param name="ticks">指定的刻度</param>
		/// <param name="endian"></param>
		/// <returns>新的 System.Data.SqlTypes.SqlGuid 对象。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlGuid GetHalfIdByTicks(SqlGuid guid, SqlInt64 ticks, SqlBoolean endian)
		{
			if (ticks.IsNull)
				return SqlGuid.Null;

			return new SqlGuid(Inner_GetIdByTicks(guid.IsNull ? Guid.Empty.ToByteArray() : guid.ToByteArray(), ticks.IsNull ? 0L : ticks.Value, full: false, endian: endian.IsNull ? null : new bool?(endian.Value)));
		}

		/// <summary>
		/// 从指定的 System.Guid 类的一个实例中取出时间值
		/// </summary>
		/// <param name="guid">指定的 System.Guid 类的一个实例</param>
		/// <param name="endian"></param>
		/// <returns>指定的 System.Guid 类的一个实例中的时间值</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetTicksFromHalfId(SqlGuid guid, SqlBoolean endian)
		{
			if (guid.IsNull)
				return SqlInt64.Null;

			return Inner_GetTicksFromId(guid.ToByteArray(), full: false, endian: endian.IsNull ? null : new bool?(endian.Value));
		}

		/// <summary>
		/// 以指定的刻度初始化 System.Data.SqlTypes.SqlGuid 类的一个新实例。
		/// </summary>
		/// <param name="guid"></param>
		/// <param name="ticks">指定的刻度</param>
		/// <param name="endian"></param>
		/// <returns>新的 System.Data.SqlTypes.SqlGuid 对象。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlGuid GetFullIdByTicks(SqlGuid guid, SqlInt64 ticks, SqlBoolean endian)
		{
			if (ticks.IsNull)
				return SqlGuid.Null;

			return new SqlGuid(Inner_GetIdByTicks(guid.IsNull ? Guid.Empty.ToByteArray() : guid.ToByteArray(), ticks.IsNull ? 0L : ticks.Value, full: true, endian: endian.IsNull ? null : new bool?(endian.Value)));
		}

		/// <summary>
		/// 从指定的 System.Guid 类的一个实例中取出时间值
		/// </summary>
		/// <param name="guid">指定的 System.Guid 类的一个实例</param>
		/// <param name="endian"></param>
		/// <returns>指定的 System.Guid 类的一个实例中的时间值</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetTicksFromFullId(SqlGuid guid, SqlBoolean endian)
		{
			if (guid.IsNull)
				return SqlInt64.Null;

			return Inner_GetTicksFromId(guid.ToByteArray(), full: true, endian: endian.IsNull ? null : new bool?(endian.Value));
		}

		/// <summary>
		/// 以指定的刻度初始化 System.Data.SqlTypes.SqlGuid 类的一个新实例。
		/// </summary>
		/// <param name="guid"></param>
		/// <param name="ticks">指定的刻度</param>
		/// <param name="full"></param>
		/// <param name="endian"></param>
		/// <returns>新的 System.Data.SqlTypes.SqlGuid 对象。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlGuid GetIdByTicks(SqlGuid guid, SqlInt64 ticks, SqlBoolean full, SqlBoolean endian)
		{
			if (ticks.IsNull)
				return SqlGuid.Null;

			return new SqlGuid(Inner_GetIdByTicks(guid.IsNull ? Guid.Empty.ToByteArray() : guid.ToByteArray(), ticks.IsNull ? 0L : ticks.Value, full: full.IsNull ? false : full.Value, endian: endian.IsNull ? null : new bool?(endian.Value)));
		}

		/// <summary>
		/// 从指定的 System.Guid 类的一个实例中取出时间值
		/// </summary>
		/// <param name="guid">指定的 System.Guid 类的一个实例</param>
		/// <param name="full"></param>
		/// <param name="endian"></param>
		/// <returns>指定的 System.Guid 类的一个实例中的时间值</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetTicksFromId(SqlGuid guid, SqlBoolean full, SqlBoolean endian)
		{
			if (guid.IsNull)
				return SqlInt64.Null;

			return Inner_GetTicksFromId(guid.ToByteArray(), full: full.IsNull ? false : full.Value, endian: endian.IsNull ? null : new bool?(endian.Value));
		}

		/// <summary/>
		public static byte[] Inner_GetIdByTicks(byte[] bs, long ticks, bool full, bool? endian)
		{
			var i = full ? 0 : 2;
			var bsDt = BitConverter.GetBytes(ticks);
			if ((endian == null && BitConverter.IsLittleEndian) || endian == true)
			{
				i = bsDt.Length - i;
				//bs[0x08] = bsDt[--i];
				//bs[0x09] = bsDt[--i];
				bs[0x0A] = bsDt[--i];
				bs[0x0B] = bsDt[--i];
				bs[0x0C] = bsDt[--i];
				bs[0x0D] = bsDt[--i];
				bs[0x0E] = bsDt[--i];
				bs[0x0F] = bsDt[--i];
				if (i > 0)
				{
					bs[0x08] = bsDt[--i];
					bs[0x09] = bsDt[--i];
				}
			}
			else
			{
				//bs[0x08] = bsDt[i++];
				//bs[0x09] = bsDt[i++];
				bs[0x0A] = bsDt[i++];
				bs[0x0B] = bsDt[i++];
				bs[0x0C] = bsDt[i++];
				bs[0x0D] = bsDt[i++];
				bs[0x0E] = bsDt[i++];
				bs[0x0F] = bsDt[i++];
				if (bsDt.Length > i)
				{
					bs[0x08] = bsDt[i++];
					bs[0x09] = bsDt[i++];
				}
			}
			return bs;
		}

		/// <summary/>
		public static long Inner_GetTicksFromId(byte[] bs, bool full, bool? endian)
		{
			if ((endian == null && BitConverter.IsLittleEndian) || endian == true)
				bs = new byte[] { bs[9], bs[8], bs[15], bs[14], bs[13], bs[12], bs[11], bs[10], 0, 0, };
			else
				bs = new byte[] { 0, 0, bs[10], bs[11], bs[12], bs[13], bs[14], bs[15], bs[8], bs[9] };
			return BitConverter.ToInt64(bs, full ? 0 : 2);
		}

		#endregion

		#region DateTime

		/// <summary>
		/// Now
		/// </summary>
		/// <returns>SqlDateTime</returns>
		[SqlFunction]
		public static DateTimeOffset GetNow()
		{
			return DateTimeOffset.Now;
		}

		/// <summary>
		/// UtcNow
		/// </summary>
		/// <returns>SqlDateTime</returns>
		[SqlFunction]
		public static DateTimeOffset GetUtcNow()
		{
			return DateTimeOffset.UtcNow;
		}

		/// <summary>
		/// GetJsDateTicks
		/// </summary>
		/// <param name="minuend">被减数</param>
		/// <param name="subtrahend">减数</param>
		/// <returns>时间差</returns>
		[SqlFunction(IsDeterministic = true)]
		public static SqlDouble GetJsDateTicks(SqlDateTime minuend, SqlDateTime subtrahend)
		{
			if (minuend.IsNull)
				return SqlDouble.Null;

			if (subtrahend.IsNull)
				subtrahend = new SqlDateTime(1970, 1, 1);
			return (minuend.Value - subtrahend.Value).TotalMilliseconds;
		}

		/// <summary>
		/// FromJsDateTicks
		/// </summary>
		/// <param name="ticks">SqlDouble</param>
		/// <returns>SqlDateTime</returns>
		[SqlFunction(IsDeterministic = true)]
		public static SqlDateTime FromJsDateTicks(SqlDouble ticks)
		{
			var js = new DateTime(1970, 1, 1);
			if (ticks.IsNull)
				return js;

			return js.AddMilliseconds(ticks.Value);
		}

		/// <summary>
		/// GetDateTime
		/// </summary>
		/// <param name="input"></param>
		/// <param name="offset"></param>
		/// <returns>时间差</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDateTime GetDateTime(DateTimeOffset input, SqlInt64 offset)
		{
			return new SqlDateTime(new DateTimeOffset(input.UtcTicks, offset.IsNull ? TimeSpan.Zero : TimeSpan.FromTicks(offset.Value)).LocalDateTime);
		}

		/// <summary>
		/// GetDateTime
		/// </summary>
		/// <param name="input"></param>
		/// <returns>时间差</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetDateTimeOffset(Nullable<DateTimeOffset> input)
		{
			if (input == null)
				return SqlInt64.Null;

			return new SqlInt64(input.Value.Offset.Ticks);
		}

		/// <summary>
		/// GetDateTimeTicks
		/// </summary>
		/// <param name="minuend">被减数</param>
		/// <param name="subtrahend">减数</param>
		/// <returns>时间差</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetDateTimeTicks(SqlDateTime minuend, SqlDateTime subtrahend)
		{
			if (minuend.IsNull)
				return SqlInt64.Null;

			if (subtrahend.IsNull)
				return new SqlInt64(minuend.Value.Ticks);

			return new SqlInt64(minuend.Value.Ticks - subtrahend.Value.Ticks);
		}

		/// <summary>
		/// FromDateTimeTicks
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlDateTime</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDateTime FromDateTimeTicks(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlDateTime.Null;

			return new SqlDateTime(new DateTime(ticks.Value));
		}

		/// <summary>
		/// FromDateTimeTicks
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <param name="offset">SqlInt64</param>
		/// <returns>SqlDateTime</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static DateTimeOffset FromDateTimeOffsetTicks(SqlInt64 ticks, SqlInt64 offset)
		{
			if (ticks.IsNull)
				return DateTimeOffset.UtcNow;

			return new DateTimeOffset(ticks.Value, offset.IsNull ? TimeSpan.Zero : TimeSpan.FromTicks(offset.Value));
		}

		/// <summary>
		/// FromDateTime
		/// </summary>
		/// <param name="input">SqlDateTime</param>
		/// <param name="offset">SqlInt64</param>
		/// <returns>SqlDateTime</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static DateTimeOffset FromDateTime(SqlDateTime input, SqlInt64 offset)
		{
			if (input.IsNull)
				return DateTimeOffset.UtcNow;

			return new DateTimeOffset(input.Value, offset.IsNull ? TimeSpan.Zero : TimeSpan.FromTicks(offset.Value));
		}

		/// <summary>
		/// FromDateTimeString
		/// </summary>
		/// <param name="input">SqlDateTime</param>
		/// <returns>SqlDateTime</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDateTime FromDateTimeString(SqlString input)
		{
			if (input.IsNull || string.IsNullOrEmpty(input.Value))
				return SqlDateTime.Null;

			var dt = DateTime.MinValue;
			if (DateTime.TryParse(input.Value, out dt))
				return new SqlDateTime(dt);

			return SqlDateTime.Null;
		}

		/// <summary>
		/// FromDateTimePart
		/// </summary>
		/// <param name="year">SqlInt32</param>
		/// <param name="month">SqlInt32</param>
		/// <param name="day">SqlInt32</param>
		/// <param name="hour">SqlInt32</param>
		/// <param name="minute">SqlInt32</param>
		/// <param name="second">SqlInt32</param>
		/// <param name="millisecond">SqlDouble</param>
		/// <returns>SqlDateTime</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDateTime FromDateTimePart(SqlInt32 year, SqlInt32 month, SqlInt32 day, SqlInt32 hour, SqlInt32 minute, SqlInt32 second, SqlDouble millisecond)
		{
			return new SqlDateTime(year.IsNull ? 0 : year.Value,
				month.IsNull ? 0 : month.Value,
				day.IsNull ? 0 : day.Value,
				hour.IsNull ? 0 : hour.Value,
				minute.IsNull ? 0 : minute.Value,
				second.IsNull ? 0 : second.Value,
				millisecond.IsNull ? 0D : millisecond.Value);
		}

		/// <summary>
		/// GetDateTimeMillisecondsTicks
		/// </summary>
		/// <param name="milliseconds">SqlDouble</param>
		/// <returns>SqlInt64</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetDateTimeMillisecondsTicks(SqlDouble milliseconds)
		{
			if (milliseconds.IsNull)
				return SqlInt64.Null;

			return new SqlInt64(TimeSpan.FromMilliseconds(milliseconds.Value).Ticks);
		}

		/// <summary>
		/// GetDateTimeSecondsTicks
		/// </summary>
		/// <param name="seconds">SqlDouble</param>
		/// <returns>SqlInt64</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetDateTimeSecondsTicks(SqlDouble seconds)
		{
			if (seconds.IsNull)
				return SqlInt64.Null;

			return new SqlInt64(TimeSpan.FromSeconds(seconds.Value).Ticks);
		}

		/// <summary>
		/// GetDateTimeMinutesTicks
		/// </summary>
		/// <param name="minutes">SqlDouble</param>
		/// <returns>SqlInt64</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetDateTimeMinutesTicks(SqlDouble minutes)
		{
			if (minutes.IsNull)
				return SqlInt64.Null;

			return new SqlInt64(TimeSpan.FromMinutes(minutes.Value).Ticks);
		}

		/// <summary>
		/// GetDateTimeHoursTicks
		/// </summary>
		/// <param name="hours">SqlDouble</param>
		/// <returns>SqlInt64</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetDateTimeHoursTicks(SqlDouble hours)
		{
			if (hours.IsNull)
				return SqlInt64.Null;

			return new SqlInt64(TimeSpan.FromHours(hours.Value).Ticks);
		}

		/// <summary>
		/// GetDateTimeDaysTicks
		/// </summary>
		/// <param name="days">SqlDouble</param>
		/// <returns>SqlInt64</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 GetDateTimeDaysTicks(SqlDouble days)
		{
			if (days.IsNull)
				return SqlInt64.Null;

			return new SqlInt64(TimeSpan.FromDays(days.Value).Ticks);
		}

		/// <summary>
		/// GetDateTimeDays
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlDouble</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDouble GetDateTimeDays(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlDouble.Null;

			return new SqlDouble(TimeSpan.FromTicks(ticks.Value).TotalDays);
		}

		/// <summary>
		/// GetDateTimeHours
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlDouble</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDouble GetDateTimeHours(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlDouble.Null;

			return new SqlDouble(TimeSpan.FromTicks(ticks.Value).TotalHours);
		}

		/// <summary>
		/// GetDateTimeMinutes
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlDouble</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDouble GetDateTimeMinutes(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlDouble.Null;

			return new SqlDouble(TimeSpan.FromTicks(ticks.Value).TotalMinutes);
		}

		/// <summary>
		/// GetDateTimeSeconds
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlDouble</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDouble GetDateTimeSeconds(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlDouble.Null;

			return new SqlDouble(TimeSpan.FromTicks(ticks.Value).TotalSeconds);
		}

		/// <summary>
		/// GetDateTimeMilliseconds
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlDouble</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlDouble GetDateTimeMilliseconds(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlDouble.Null;

			return new SqlDouble(TimeSpan.FromTicks(ticks.Value).TotalMilliseconds);
		}

		/// <summary>
		/// GetDateTimeDayOfWeek
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlInt32</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt32 GetDateTimeDayOfWeek(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlInt32.Null;

			return new SqlInt32((int)new DateTime(ticks.Value).DayOfWeek);
		}

		/// <summary>
		/// GetDateTimeDayOfYear
		/// </summary>
		/// <param name="ticks">SqlInt64</param>
		/// <returns>SqlInt32</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt32 GetDateTimeDayOfYear(SqlInt64 ticks)
		{
			if (ticks.IsNull)
				return SqlInt32.Null;

			return new SqlInt32(new DateTime(ticks.Value).DayOfYear);
		}

		/// <summary>
		/// FormatDateTime
		/// </summary>
		/// <param name="input">SqlDateTime</param>
		/// <param name="format">SqlString</param>
		/// <returns>SqlString</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlString FormatDateTime(SqlDateTime input, SqlString format)
		{
			if (input.IsNull)
				return null;

			if (format.IsNull || string.IsNullOrEmpty(format.Value))
				return new SqlString(input.Value.ToString());

			return new SqlString(input.Value.ToString(format.Value));
		}

		#endregion

		/// <summary/>
		[SqlFunction(DataAccess = DataAccessKind.Read)]
		public static SqlString Debug(SqlString path, SqlString value)
		{
			if (value.IsNull)
				value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffff");
			if (!path.IsNull)
			{
				File.AppendAllText(path.Value, value.Value + Environment.NewLine);
				return path;
			}

			if (SqlContext.IsAvailable && SqlContext.Pipe != null)
			{
				SqlContext.Pipe.Send(value.Value);
				return value;
			}

			return SqlString.Null;
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false, DataAccess = DataAccessKind.Read)]
		public static SqlString DebugDeterministic(SqlString path, SqlString value)
		{
			return Other.Debug(path, value);
		}

		/// <summary>
		/// 测试指定的IP类型的字符串位置是否为真
		/// </summary>
		/// <param name="data">被测流</param>
		/// <param name="ip">IP类型的字符串，为四段或四段以下格式，如：【127.0.0.0】，【11,22,33】，【44-55】</param>
		/// <returns>是否为真</returns>
		[Obsolete]
		//[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBoolean TestBinaryAtBitIP(SqlBinary data, SqlString ip)
		{
			if (ip.IsNull || string.IsNullOrEmpty(ip.Value))
				return new SqlBoolean(false);

			string[] ts = ip.Value.Split(new char[] { '.', ',', ';', ':', '-', '|', '/', ' ', '\t', '\r', '\n', '\'' }, StringSplitOptions.RemoveEmptyEntries);
			byte[] bs = new byte[4];
			int i;
			byte b;
			Array.Reverse(ts);
			for (i = 0; i < ts.Length && i < bs.Length; i++)
			{
				if (byte.TryParse(ts[i], out b))
					bs[i] = b;
				else
					return new SqlBoolean(false);
			}
			i = BitConverter.ToInt32(bs, 0);
			return TestBinaryAtBitIndex(data, i);
		}

		/// <summary>
		/// 测试指定的IP类型的字符串位置是否为真
		/// </summary>
		/// <param name="data">被测流</param>
		/// <param name="index">二进制数据位的位置</param>
		/// <returns>是否为真</returns>
		[Obsolete]
		//[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBoolean TestBinaryAtBitIndex(SqlBinary data, SqlInt32 index)
		{
			if (data.IsNull || data.Value == null)
				return new SqlBoolean(false);

			var i = data.Length - index.Value / 8 - 1;
			if (i < 0)
				return new SqlBoolean(false);

			switch (index.Value % 8)
			{
				case 7:
					return new SqlBoolean((data[i] & 0x80) != 0);
				case 6:
					return new SqlBoolean((data[i] & 0x40) != 0);
				case 5:
					return new SqlBoolean((data[i] & 0x20) != 0);
				case 4:
					return new SqlBoolean((data[i] & 0x10) != 0);
				case 3:
					return new SqlBoolean((data[i] & 0x08) != 0);
				case 2:
					return new SqlBoolean((data[i] & 0x04) != 0);
				case 1:
					return new SqlBoolean((data[i] & 0x02) != 0);
				default:
					return new SqlBoolean((data[i] & 0x01) != 0);
			}
			//return new SqlBoolean(false);
		}
	}
}
